#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "parser.h"
#include "operations.h"
#include "graph.h"
#include "solution.h"
#include "tabooState.h"

/** Documentazione temporanea di una funzione temporaneissima che però da qualche parte se ne andrà, magari in main-tools.
 * L'idea è che essa sia responsabile di quante più inizializzazioni possibile, ma già initCompleteGraph() in parser.c la tradisce. */
void initStructures(Psolution* ps, PtabooState* pts,int* k, int* n);
void printStructures(FILE* f, Psolution ps, PtabooState pts);
void printVehicleStructures(FILE* f, PvehicleState pvs, PtabooList ptl, TabooExpire now, int k);
void modifySolution(Pgraph pg, Psolution sol, PtabooState pts);

int main(int argn,const char** args){

	Psolution p_solution;
	PtabooState p_tabooState;
	Pgraph p_graph;

	int __K__;
	int __N__;

	FILE* f_in;

	if (argn==3){
		f_in = fopen(args[1],"r");
		__K__ = atoi(args[2]);
	}else{
		printf("numero di parametri passati errati.\n");
		return EXIT_FAILURE;
	}

	p_graph = parseGraph(f_in, &__N__);
	dijkstraFiller(p_graph);
	//initSmartWeights(p_graph);
	printWholeMatrix(stdout, p_graph);

	initStructures(&p_solution, &p_tabooState, &__K__, &__N__);
	printStructures(stdout, p_solution, p_tabooState);
	modifySolution(p_graph, p_solution, p_tabooState);

	printf("FINE.\n");
	return 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//attenzione: se non puntiamo ai puntatori, passiamo per valoreeeeeeee
void initStructures(Psolution* ps, PtabooState* pts, int* k, int* n) {
	*ps = initSolution(k,n);
	*pts = initTabooState(n,k,0);
}

void printStructures(FILE* f, Psolution ps, PtabooState pts) {
	printSolution(f, ps);
	printTabooState(f, pts, 0);
}
void printVehicleStructures(FILE* f, PvehicleState pvs, PtabooList ptl, TabooExpire now, int k) {
	printVehicleState(f, pvs, k);
	//printTabooListExpirations(f, ptl, now, k);
	printTabooListTenures(f, ptl, now, k);
}

void modifySolution(Pgraph pg, Psolution ps, PtabooState pts) {

	int k1 = 0, k2 = 1;
	PedgeID _21=initEdgeID(0,1);
	validateEdgeID(_21);
	PedgeID _51=initEdgeID(0,4);
	validateEdgeID(_51);
	PedgeID _34=initEdgeID(2,3);
	validateEdgeID(_34);
	PedgeID _78=initEdgeID(6,7);//non viene mai inserito!
	validateEdgeID(_78);
	PedgeID _23=initEdgeID(1,2);
	validateEdgeID(_23);
	PedgeID _24=initEdgeID(3,1);
	validateEdgeID(_24);

	TabooExpire datak1 = 0, datak2 = 0;
	printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
	addEdgeOp(_21, getEdgeGraph(pg, _21), ps->states[k1], ps->gMatrix, k1, pts->tls[k1], datak1, 0, 1);
		printVehicleStructures(stdout, ps->states[k1], pts->tls[k1], datak1, k1);
		printGMatrix(stdout, ps->gMatrix);
	datak1++;
	printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
	addEdgeOp(_51, getEdgeGraph(pg, _51), ps->states[k1], ps->gMatrix, k1, pts->tls[k1], datak1, 0, 1);
		printVehicleStructures(stdout, ps->states[k1], pts->tls[k1], datak1, k1);
		printGMatrix(stdout, ps->gMatrix);
	datak1++;
	printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
	addEdgeOp(_23, getEdgeGraph(pg, _23), ps->states[k1], ps->gMatrix, k1, pts->tls[k1], datak1, 0, 1);
			printVehicleStructures(stdout, ps->states[k1], pts->tls[k1], datak1, k1);
			printGMatrix(stdout, ps->gMatrix);
	datak1++;
	printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
	addEdgeOp(_34, getEdgeGraph(pg, _34), ps->states[k1], ps->gMatrix, k1, pts->tls[k1], datak1, 0, 1);
			printVehicleStructures(stdout, ps->states[k1], pts->tls[k1], datak1, k1);
			printGMatrix(stdout, ps->gMatrix);
	datak1++;
	printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
	addEdgeOp(_24, getEdgeGraph(pg, _24), ps->states[k1], ps->gMatrix, k1, pts->tls[k1], datak1, 0, 1);
			printVehicleStructures(stdout, ps->states[k1], pts->tls[k1], datak1, k1);
			printGMatrix(stdout, ps->gMatrix);
	datak1++;
	printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
	addEdgeOp(_51, getEdgeGraph(pg, _51), ps->states[k1], ps->gMatrix, k1, pts->tls[k1], datak1, 0, 1);
			printVehicleStructures(stdout, ps->states[k1], pts->tls[k1], datak1, k1);
			printGMatrix(stdout, ps->gMatrix);
	datak1++;
	printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
	addEdgeOp(_21, getEdgeGraph(pg, _21), ps->states[k1], ps->gMatrix, k1, pts->tls[k1], datak1, 0, 1);
			printVehicleStructures(stdout, ps->states[k1], pts->tls[k1], datak1, k1);
			printGMatrix(stdout, ps->gMatrix);
	datak1++;
	printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
	addEdgeOp(_78, getEdgeGraph(pg, _78), ps->states[k2], ps->gMatrix, k2, pts->tls[k2], datak2, 0, 1);
			printVehicleStructures(stdout, ps->states[k2], pts->tls[k2], datak2, k2);
			printGMatrix(stdout, ps->gMatrix);
	datak2++;

	//printf("elimino l'arco (1,2) (doppio)\n");
	//removeEdgeIDInSolution(sol,0,_21);
	//printf("elimino l'arco (3,4)\n");
	//removeEdgeIDInSolution(sol,0,_34);

	/*printf("************************* AFTER ********************************\n");
	printSolution(stdout,sol);

	printf("chi soddisfa l'arco (21)? ");
	printf("%d\n", whoGathersEdge(sol->gMatrix,_21)+1);
	printf("chi soddisfa l'arco (34)? ");
	printf("%d\n", whoGathersEdge(sol->gMatrix,_34)+1);
	printf("chi soddisfa l'arco (78)? ");
	printf("%d\n", whoGathersEdge(sol->gMatrix,_78)+1);*/

	/*printf("ora provo a usare le primitive per scorrere la soluzione:\n");
	printf("partom:\n");
	bool start=true;
	PedgeSol edge;
	PvehiclePath path=getVehiclePathInSolution(sol,0);
	resetMemory(path,DIRECTION_NEXT);
	while((edge=getNearEdgeInVehiclePath(path,DIRECTION_NEXT))!=NULL){
		start=false;
		printf("chi soddisfa l'arco (%d;%d) usando \"whoGathersEdge\"? camion %d",edge->id->i,edge->id->j,whoGathersEdge(sol,edge->id));
		printEdgeSol(stdout,edge);
		printf("\n");
	}
	printf("fine.\n"); */
}
